/**
 * 将给定的值转换为字符串。
 * 如果输入是字符串数组，则将数组元素连接成一个逗号分隔的字符串；
 * 如果输入是单个字符串，则直接返回该字符串。
 *
 * @param value 可以是字符串或者字符串数组。
 * @returns 返回处理后的字符串。
 */
export function convertToString(value: string | string[]): string {
  return Array.isArray(value) ? value.join(',') : value;
}

/**
 * 求两个数组的对称差集（补集）
 * @param array1 第一个数组
 * @param array2 第二个数组
 * @returns 对称差集数组，包含所有在 array1 或 array2 中但不在两者交集中的元素
 */
export function symmetricDifference<T>(array1: T[], array2: T[]): T[] {
  const set1 = new Set(array1);
  const set2 = new Set(array2);

  const difference = new Set<T>();

  // 在 array1 中但不在 array2 中的元素
  array1.forEach((item) => {
    if (!set2.has(item)) {
      difference.add(item);
    }
  });

  // 在 array2 中但不在 array1 中的元素
  array2.forEach((item) => {
    if (!set1.has(item)) {
      difference.add(item);
    }
  });

  return Array.from(difference);
}

/**
 * 比较两个数组，返回一个对象，包含两个数组中相同和不同的元素
 *
 * @param arr1 第一个数组
 * @param arr2 第二个数组
 * @returns 返回一个对象，其中same属性是两个数组中相同的元素数组，different属性是两个数组中不同的元素数组
 */
export function compareArrays(arr1: string[], arr2: string[]): { same: string[]; different: string[] } {
  // 使用Set数据结构存储数组元素，以便快速查找和去重
  const set1 = new Set(arr1);
  const set2 = new Set(arr2);
  // 初始化用于存储相同元素的数组
  const same: string[] = [];
  // 初始化用于存储不同元素的数组
  const different: string[] = [];

  // 遍历第一个数组，判断元素是否同时存在于第二个数组中
  arr1.forEach((item) => {
    if (set2.has(item)) {
      // 如果元素同时存在于第二个数组中，则将其添加到same数组中
      same.push(item);
    } else {
      // 如果元素不存在于第二个数组中，则将其添加到different数组中
      different.push(item);
    }
  });

  // 遍历第二个数组，将不在第一个数组中存在的元素添加到different数组中
  arr2.forEach((item) => {
    if (!set1.has(item)) {
      different.push(item);
    }
  });

  // 返回包含相同和不同元素的对象
  return { same, different };
}

/**
 * 深度克隆一个给定的对象。
 *
 * 深度克隆是指将对象完全复制一份，包括其内部的引用类型也是完全复制，
 * 不会共享内存。这在需要复制对象的完全独立副本时非常有用。
 *
 * @param value {T} - 需要克隆的对象。可以是任何类型的值。
 * @returns {T} - 克隆后的对象。
 */
export function deepClone<T>(value: T): T {
  // 检查值是否为基本类型或 null，如果是则直接返回。
  if (value === null || typeof value !== 'object') {
    // 基本类型（包括 null、undefined、string、number、boolean、symbol）
    return value;
  }

  // 处理特殊对象类型的深度克隆
  if (value instanceof Date) {
    return new Date(value) as T;
  }

  if (value instanceof RegExp) {
    return new RegExp(value) as T;
  }

  if (value instanceof Map) {
    return new Map(value) as T;
  }

  if (value instanceof Set) {
    return new Set(value) as T;
  }

  // 对于普通对象和数组，使用 JSON.stringify 和 JSON.parse 进行深度克隆。
  // 这种方法简单但可能不适用于所有情况，特别是对象包含循环引用或特殊对象时。
  // 在实际应用中，可能需要更复杂的深度克隆实现。
  return JSON.parse(JSON.stringify(value));
}
